package robot

import (
	"context"
	"encoding/json"
	"sale-admin/internal/app/grpc/client"
	"sale-admin/internal/app/grpc/protoc/devicec"
	"sale-admin/internal/app/grpc/protoc/system_admin"
	"sale-admin/internal/app/web/schema"
	"sale-admin/internal/dal"
	"sale-admin/internal/dao"
	"sale-admin/internal/define"
	"sale-admin/internal/models"
	"strconv"
	"strings"
	"time"

	"192.168.1.75/go-pkg/errorx"
	"192.168.1.75/go-pkg/logx"
	"github.com/samber/lo"
	"github.com/shopspring/decimal"
	"gorm.io/gorm"
)

type RobotGoods struct {
}

// 定义 GoodsInfoResult结构体 --- 机器售卖商品信息返回结构体
type GoodsInfoResult struct {
	Remark   string            `json:"remark" json_old:"Remark"`
	Phone    string            `json:"phone" json_old:"Phone"`
	Data     []ResultGoodsInfo `json:"data" json_old:"Data"`
	DataSort []ResultGoodsInfo `json:"data_sort" json_old:"DataSort"` // 进行排序之后的商品数据
}

type GoodsInfoResultOld struct {
	Remark   string               `json:"remark" json_old:"Remark"`
	Phone    string               `json:"phone" json_old:"Phone"`
	Data     []ResultGoodsInfoOld `json:"data" json_old:"Data"`
	DataSort []ResultGoodsInfoOld `json:"data_sort" json_old:"DataSort"` // 进行排序之后的商品数据
}

/**
 *
 * 商品列表
 */
func (RobotGoods) GoodsInfo(
	ctx context.Context,
	db *gorm.DB,
	salesID string,
	GetDetails int,
	OnlySort string,
	Andriod string, // == 1 说明是安卓
) (
	Result GoodsInfoResult,
	err error,
) {
	// 获取商品信息 RobotInfo
	RobotInfo, robotExist := RobotService{}.CheckRobotExist(ctx, db, salesID, "")
	if !robotExist {
		err = errorx.New("找不到机器人", -1)
		return
	}
	// 定义返回的Result
	Result = GoodsInfoResult{}

	// 查询机器补货信息
	var RobotSalesInfoList []models.MaRobotSalesInfo
	tx1 := db.Model(&models.MaRobotSalesInfo{}).
		Where("sales_id = ? ", salesID).
		Where("container_status = ? ", 1)

	// if OnlySort != "" {
	if Andriod == "1" {
		tx1.Where("container_use_status = 1")
	}
	tx1.Find(&RobotSalesInfoList)

	GoodsIDDataMap := make(map[string]ResultGoodsInfo)
	GoodsContainerMap := make(map[string][]ContainerInfo)
	var GoodsIDList = []string{}
	for _, v := range RobotSalesInfoList {
		if !lo.Contains(GoodsIDList, v.GoodsID) {
			GoodsIDList = append(GoodsIDList, v.GoodsID)
		}
	}

	// 下架的商品
	offShelfGoodsIDs, _ := dao.ObjAssociation{}.GetAssociationID(context.Background(), dal.Q, define.AssociationRobotGoodsOffShelf, "", RobotInfo.RobotName)
	// 下架的推荐商品
	offShelfRecommendGoodsIDs, _ := dao.ObjAssociation{}.GetAssociationID(context.Background(), dal.Q, define.AssociationRobotRecommendedGoodsOffShelf, "", RobotInfo.RobotName)
	// 下架的广告商品
	offShelfAdGoodsIDs, _ := dao.ObjAssociation{}.GetAssociationID(context.Background(), dal.Q, define.AssociationRobotGoodsADOffShelf, "", RobotInfo.RobotName)

	// 获取商品详情
	var GoodsInfoList []models.MaGoodsInfo
	db.Model(&models.MaGoodsInfo{}).
		Where("goods_id in (?)", GoodsIDList).
		Find(&GoodsInfoList)

	var GoodsInfoMap = make(map[string]models.MaGoodsInfo)
	var merchantIDs []string
	var merchantMap = make(map[string]string)
	for _, v := range GoodsInfoList {
		if _, ok := GoodsInfoMap[v.GoodsID]; !ok {
			// 下架的广告商品，不显示
			if lo.Contains(offShelfAdGoodsIDs, v.GoodsID) {
				v.AdImage = ""
			}
			// 下架的商品推荐，不显示
			if lo.Contains(offShelfRecommendGoodsIDs, v.GoodsID) {
				v.Recommend = 2
				v.RecommendImage = ""
			}
			// 去除下架的商品，只显示上架的商品
			if !lo.Contains(offShelfGoodsIDs, v.GoodsID) {
				GoodsInfoMap[v.GoodsID] = v
				merchantIDs = append(merchantIDs, v.MerchantID)
			}
		}
	}
	// 获取商户名称
	cli, err := client.GetSystemAdminClient()
	if err == nil {
		rsp, err := cli.MerchantName(context.Background(), &system_admin.MerchantNameReq{
			MerchantIds: merchantIDs,
		})
		if err == nil && rsp != nil {
			merchantMap = rsp.MerchantNameMap
		}
	}
	// 遍历补货里面的商品数据
	myGoodsInventory := make(map[string]int)
	for _, v := range RobotSalesInfoList {
		// 定义Data
		var ItemData ResultGoodsInfo
		ItemData.SalesID = v.SalesID
		ItemData.GoodsID = v.GoodsID
		ItemData.GoodsInventory = v.GoodsInventory
		ItemData.GoodsMaxInventory = v.GoodsMaxInventory
		ItemData.GoodsReserveInventory = v.GoodsReserveInventory
		ItemData.ContainerFloor = v.ContainerFloor
		ItemData.ContainerNum = v.ContainerNum
		ItemData.AddTime = v.AddTimeFormated
		ItemData.ClassID = v.ClassID
		ItemData.GoodsStatus = v.GoodsStatus
		ItemData.ContainerType = v.ContainerType
		ItemData.Sort = v.Sort
		ItemData.ContainerStatus = v.ContainerStatus
		ItemData.ContainerUseStatus = v.ContainerUseStatus
		ItemData.CreatedAt = v.CreatedAt
		if _, ok := GoodsInfoMap[v.GoodsID]; !ok {
			continue
		}
		GoodsInfo := GoodsInfoMap[v.GoodsID]
		if GoodsInfo.MerchantID == "" {
			continue
		}
		ItemData.Merchant = merchantMap[GoodsInfo.MerchantID] //  产品所属商户名称
		if GoodsInfo.GoodsImage == "" {
			GoodsInfo.GoodsImage = "/static/default_image.png"
		}
		ItemData.VoiceKeywords = GoodsInfo.VoiceKeywords
		if GetDetails == 1 {
			ItemData.Price = GoodsInfo.Price
			ItemData.GoodsName1 = GoodsInfo.GoodsName1
			ItemData.GoodsDescription1 = GoodsInfo.GoodsDescription1
			ItemData.GoodsImage = GoodsInfo.GoodsImage
			ItemData.TotalSales = GoodsInfo.TotalSales
			ItemData.GoodsCode = GoodsInfo.GoodsCode
			ItemData.UseRC = GoodsInfo.UseRC
			ItemData.GoodsName2 = GoodsInfo.GoodsName2
			ItemData.GoodsDescription2 = GoodsInfo.GoodsDescription2
			ItemData.GoodsName3 = GoodsInfo.GoodsName3
			ItemData.GoodsDescription3 = GoodsInfo.GoodsDescription3
			ItemData.CodeImage = GoodsInfo.CodeImage
			ItemData.IsAuth = GoodsInfo.IsAuth
			ItemData.Price1 = GoodsInfo.Price1
			ItemData.GoodsDetail = GoodsInfo.GoodsDetail
			ItemData.GoodsVoice = GoodsInfo.GoodsVoice
			ItemData.ShowTag = GoodsInfo.ShowTag
			ItemData.GoodsType = GoodsInfo.GoodsType
			ItemData.Spring = GoodsInfo.Spring
			ItemData.Points = GoodsInfo.Points
			ItemData.PointsSupport = GoodsInfo.PointsSupport
			ItemData.TagCode = GoodsInfo.TagCode
			ItemData.PurchaseType = GoodsInfo.PurchaseType
		}
		// 定义每个货道的信息，包含4个参数（货道号、楼层号、剩余库存，最大容量库存）
		ItemData.Container = []ContainerInfo{}
		Result.Data = append(Result.Data, ItemData)
		// 判断当前的货道状态 0 下架 1上架
		if v.ContainerStatus != 0 { // 已上架
			var GoodsOnContainerDetail ResultGoodsInfo
			GoodsOnContainerDetail.ContainerStatus = v.ContainerStatus
			GoodsOnContainerDetail.ClassID = v.ClassID
			GoodsOnContainerDetail.GoodsID = v.GoodsID
			GoodsOnContainerDetail.Sort = v.Sort
			GoodsOnContainerDetail.UseRC = GoodsInfo.UseRC
			GoodsOnContainerDetail.GoodsInventory += v.GoodsInventory            // 累加当前商品的剩余库存
			myGoodsInventory[v.GoodsID] += GoodsOnContainerDetail.GoodsInventory // 累加当前商品的剩余库存
			GoodsContainerMap[v.GoodsID] = append(GoodsContainerMap[v.GoodsID], ContainerInfo{
				Num:          v.ContainerNum,
				Floor:        v.ContainerFloor,
				Inventory:    uint(v.GoodsInventory),
				MaxInventory: uint(v.GoodsMaxInventory),
			})
			GoodsOnContainerDetail.Container = GoodsContainerMap[v.GoodsID]
			GoodsIDDataMap[v.GoodsID] = GoodsOnContainerDetail
		}
	}
	for _, v := range GoodsIDDataMap {
		item := v
		if GetDetails == 1 {
			if _, ok := GoodsInfoMap[v.GoodsID]; !ok {
				continue
			}
			GoodsInfo := GoodsInfoMap[v.GoodsID]
			if GoodsInfo.MerchantID == "" {
				continue
			}

			if GoodsInfo.GoodsImage == "" {
				GoodsInfo.GoodsImage = "/static/default_image.png"
			}
			// 角标ID
			if GoodsInfo.CornerLabelID != "" {
				// 获取角标图片地址
				var cornerLabelInfo models.MaGoodsCornerLabel
				db.Model(&models.MaGoodsCornerLabel{}).
					Where("id = ?", GoodsInfo.CornerLabelID).Take(&cornerLabelInfo)
				item.CornerLabelImage = cornerLabelInfo.Image
			}
			item.Price = GoodsInfo.Price
			item.GoodsName1 = GoodsInfo.GoodsName1
			item.GoodsDescription1 = GoodsInfo.GoodsDescription1
			item.GoodsImage = GoodsInfo.GoodsImage
			item.TotalSales = GoodsInfo.TotalSales
			item.GoodsCode = GoodsInfo.GoodsCode
			item.UseRC = GoodsInfo.UseRC
			item.GoodsName2 = GoodsInfo.GoodsName2
			item.GoodsDescription2 = GoodsInfo.GoodsDescription2
			item.GoodsName3 = GoodsInfo.GoodsName3
			item.GoodsDescription3 = GoodsInfo.GoodsDescription3
			item.CodeImage = GoodsInfo.CodeImage
			item.IsAuth = GoodsInfo.IsAuth
			item.Price1 = GoodsInfo.Price1
			item.GoodsDetail = GoodsInfo.GoodsDetail
			item.GoodsVoice = GoodsInfo.GoodsVoice
			item.ShowTag = GoodsInfo.ShowTag
			item.GoodsType = GoodsInfo.GoodsType
			item.Spring = GoodsInfo.Spring
			item.GoodsInventory = myGoodsInventory[GoodsInfo.GoodsID]
			item.Points = GoodsInfo.Points
			item.PointsSupport = GoodsInfo.PointsSupport
			item.VoiceKeywords = GoodsInfo.VoiceKeywords
			item.Recommend = GoodsInfo.Recommend
			item.RecommendImage = GoodsInfo.RecommendImage
			item.AdImage = GoodsInfo.AdImage
			item.TagCode = GoodsInfo.TagCode
			item.PurchaseType = GoodsInfo.PurchaseType
		}
		// 商品列表不显示赠品
		if item.GoodsType != 7 {
			Result.DataSort = append(Result.DataSort, item)
		}
	}
	// 只返回dataSort数组
	// !="1",返回Data和DataSort两个数组
	// DataSort是货道集合，Data商品集合
	if OnlySort == "1" {
		Result.Data = []ResultGoodsInfo{}
	}

	// 获取机器服务电话
	Result.Phone, _ = RobotGoods{}.getServicePhone(RobotInfo.MerchantID, salesID)
	// 绑定商品属性。比如是否是多规格，是否属于加购服务
	if len(Result.DataSort) > 0 {
		// 获取多规格商品信息
		RobotGoods{}.getMultiGoods(db, &Result, salesID)
		// 获取加购商品信息
		RobotGoods{}.getAddPurchaseGoods(db, &Result, salesID)
	}
	// 商品备注
	Result.Remark = "购买过程中，如需帮助请拨打客服电话##购买过程中，如需帮助请拨打客服电话"
	if RobotInfo.Remark != "" {
		Result.Remark = RobotInfo.Remark
	}
	return Result, nil
}

// 获取机器服务电话
func (RobotGoods) getServicePhone(merchantID, SalesID string) (
	phone string,
	err error,
) {
	// grpc 设备后台获取机器的服务电话
	req := &devicec.DeviceListReq{}
	req.MerchantId = merchantID
	deviceClient, clientErr := client.GetDeviceAdminClient()
	if clientErr != nil {
		logx.Error(context.Background(), "grpc device client error", logx.Err(clientErr))
		return
	}
	res, err := deviceClient.DeviceList(context.Background(), req)
	if res != nil && res.Code == 0 && err == nil {
		for _, v := range res.List {
			if v.IdentificationCode == SalesID {
				phone = strings.ReplaceAll(v.ServicePhone, "\t", "")
			}
		}
	}
	return phone, err
}

// 检查当前商品是否有折扣
func (RobotGoods) CheckGoodsOfActivity(ctx context.Context, db *gorm.DB, salesID string) (count int) {

	// 定义切片
	goodsActivityData := []schema.AllGoodsActivityDataDetail{}
	// 获取当前机器下的所有活动规则
	db.Table(models.MaGoodsActivity{}.TableName()+" as a1").
		Joins("LEFT JOIN "+models.MaGoodsActivityDetail{}.TableName()+" as a2 ON a1.id = a2.activity_id").
		Where("a1.sales_id = ?", salesID).              // 当前机器
		Where("a1.start_time <= ?", time.Now().Unix()). // 所属的时间范围必须有效 开始时间需要小于当前时间
		Where("a1.end_time >= ?", time.Now().Unix()).   // 所属的时间范围必须有效 结束时间需要大于当前时间
		Select("a1.*,a2.*").
		Find(&goodsActivityData)
	if len(goodsActivityData) == 0 {
		return 0
	} else {
		// 检查当前的商品是否属于关联优惠商品之一。同时检查折扣是否相同. 不相同则提示异常
		// ...
		return len(goodsActivityData)
	}
}

// 获取机器 【加购商品】 的触发商品和优惠商品
func (RobotGoods) getAddPurchaseGoods(db *gorm.DB, res *GoodsInfoResult, salesID string) {
	// 1.获取当前机器的活动商品 注：（一台机器可以拥有多个规则）
	goodsActivityData := []schema.AllGoodsActivityDataDetail{}
	// 【切片】获取当前机器的所有活动商品信息
	db.Table(models.MaGoodsActivity{}.TableName()+" as a1").
		Joins("LEFT JOIN "+models.MaGoodsActivityDetail{}.TableName()+" as a2 ON a1.id = a2.activity_id").
		Where("a1.sales_id = ?", salesID).              // 当前机器
		Where("a1.start_time <= ?", time.Now().Unix()). // 所属的时间范围必须有效 开始时间需要小于当前时间
		Where("a1.end_time >= ?", time.Now().Unix()).   // 所属的时间范围必须有效 结束时间需要大于当前时间
		Select("a1.*,a2.*").
		Find(&goodsActivityData)
	if len(goodsActivityData) == 0 {
		return
	}
	// 2.给触发商品新增对应的优惠商品
	GoodsMap := make(map[string]float64)
	for _, v := range res.DataSort {
		GoodsMap[v.GoodsID] = v.Price // 装本地在售卖的商品ID
	}
	// 定义Map
	ActivityGoodsPreMap := make(map[string][][]MultiDiscountGoodsInfo)
	ActivityGoodsMap := make(map[string][]MultiDiscountGoodsInfo)
	// 开始循环当前生效期间的所有活动. 1.多个活动的商品，需要同时一起生效。 2.如果多个活动，添加了同一个商品对应的优惠商品，取最低折扣的商品
	for _, v := range goodsActivityData {

		newGoodsJson := []MultiDiscountGoodsInfo{}

		// 过滤第一层数据
		if _, ok := GoodsMap[v.GoodsID]; ok {

			goodsJson := []MultiDiscountGoodsInfo{}
			json.Unmarshal([]byte(v.MultiDiscountGoods), &goodsJson) // json_decode
			// 匹配当前商品的价格
			for _, n := range goodsJson {
				if _, ok := GoodsMap[n.GoodsID]; ok {
					// type == 1为折扣价 type == 2 换购价 （ 二选一原则）
					// 为了方便，不管折扣还是换购，安卓只使用 DiscountPrice
					if v.Type == "1" {
						// 使用折扣价
						// a.获取折扣，用于计算价格
						mydiscount, _ := strconv.ParseFloat(n.Discount, 64)
						// b.精度计算(折扣后的价格)
						myprice := decimal.NewFromFloat(mydiscount).Mul(decimal.NewFromFloat(GoodsMap[n.GoodsID])).InexactFloat64()
						if myprice < 0.01 {
							myprice = 0.01
						}
						n.DiscountPrice = strconv.FormatFloat(myprice, 'f', 2, 64) // 折扣后的价格
					} else if v.Type == "2" {
						// 使用换购价
						n.Discount = "0"
						n.DiscountPrice = n.ExchangePrice
					}

					// if n.ExchangePrice == "" || n.ExchangePrice == "0" {

					// } else {

					// }

					n.Price = strconv.FormatFloat(GoodsMap[n.GoodsID], 'f', 2, 64) // 商品原价
				}

				// 一个活动，如果有多个商品的折扣不同，那么取最低折扣优惠商品返回

				newGoodsJson = append(newGoodsJson, n)
			}

			if len(newGoodsJson) > 0 {
				ActivityGoodsPreMap[v.GoodsID] = append(ActivityGoodsPreMap[v.GoodsID], newGoodsJson) // 一个商品对应的多个活动的优惠商品的
				ActivityGoodsMap[v.GoodsID] = newGoodsJson                                            // 选取最低优惠，赋给当前的商品ID。
			}
		}
	}
	// 1. array_merge 多个活动的优惠商品进行合并，
	// 2. 比较，取折扣最低的优惠商品ID。
	myzhenghe := make(map[string][]MultiDiscountGoodsInfo) // 需要去重，并且保留折扣最低的优惠商品
	for goodsID, OneGoodsActivity := range ActivityGoodsPreMap {

		// 多个活动的
		myGoodsIDs := make(map[string]string)

		// OneGoodsGroup - 单个商品下的多组活动优惠组合
		// 当前商品整合后的对应优惠商品并集
		for _, val := range OneGoodsActivity {
			// val - 每组活动下对应的单个或多个商品信息。
			for _, v := range val {
				// 判断是否存在myGoodsIDs是否存在
				if myGoodsIDs[v.GoodsID] != "" {
					if myGoodsIDs[v.GoodsID] > v.Discount {
						myGoodsIDs[v.GoodsID] = v.Discount
						myzhenghe[goodsID] = append(myzhenghe[goodsID], v)
					}
				} else {
					// if myGoodsIDs[goodsID] == nil {
					// myGoodsIDs[goodsID] = map[string]string{}
					// }
					myGoodsIDs[v.GoodsID] = v.Discount
					myzhenghe[goodsID] = append(myzhenghe[goodsID], v)
				}
				// myzhenghe[goodsID] = append(myzhenghe[goodsID], v)
			}
		}
	}

	// 使用DataSort数组，对每个商品进行遍历。
	for k, v := range res.DataSort {
		if _, ok := ActivityGoodsMap[v.GoodsID]; ok {
			res.DataSort[k].Activity = 1
			res.DataSort[k].ActivityList = ActivityGoodsMap[v.GoodsID]
		}
	}
}

type MultiGoods struct {
	Multi            int      `json:"multi" json_old:"Multi"`
	MultiGroupID     string   `json:"multi_group_id" json_old:"MultiGroupID"`
	MultiGroupName   string   `json:"multi_group_name" json_old:"MultiGroupName"`
	MultiGroupDetail string   `json:"multi_group_detail" json_old:"MultiGroupDetail"`
	MultiSort        int      `json:"multi_sort" json_old:"MultiSort"`
	MultiGroupImage  []string `json:"multi_group_image" json_old:"MultiGroupImage"`
}

// 获取多规格商品信息
func (RobotGoods) getMultiGoods(db *gorm.DB, res *GoodsInfoResult, SalesID string) {
	GoodsMap := make(map[string]string)
	GoodsIDImageMap := make(map[string]string)
	for _, v := range res.DataSort {
		GoodsMap[v.GoodsID] = v.GoodsID
		GoodsIDImageMap[v.GoodsID] = v.GoodsImage
	}

	// 获取当前机器的多规格商品信息
	MultiGoodsList := []models.MaGoodsMulti{}
	db.Model(&models.MaGoodsMulti{}).
		Where("sales_id = ?", SalesID).
		Find(&MultiGoodsList)

		// 定义Map
	MultiGoodsMap := make(map[string]string)
	MultiGoodsDataMap := make(map[string]MultiGoods)
	MultiGoodsIDImageMap := make(map[string][]string) // 多规格商品id => 单商品图片切片

	// 开始循环，对多规格商品的数据进行处理
	for _, v := range MultiGoodsList {
		// 初始化数组
		goodsJson := []struct {
			GoodsID    string  `json:"GoodsID"`
			GoodsImage string  `json:"GoodsImage"`
			Price      float64 `json:"Price"`
		}{}
		// json_decode 转换成切片
		json.Unmarshal([]byte(v.MultiGoods), &goodsJson)
		// 对切片进行处理
		for _, val := range goodsJson {
			myGoodsID := val.GoodsID
			// 判断map的值是否存在
			if _, ok := GoodsMap[myGoodsID]; ok {
				MultiGoodsMap[myGoodsID] = myGoodsID
				// 多组多规格的商品
				MultiGoodsIDImageMap[v.ID] = append(MultiGoodsIDImageMap[v.ID], GoodsIDImageMap[myGoodsID])
				MultiGoodsDataMap[myGoodsID] = MultiGoods{
					MultiGroupID:     v.ID,
					MultiGroupName:   v.GoodsName,
					MultiGroupDetail: v.GoodsDetail,
					MultiSort:        v.MultiSort,
				}
			}
		}
	}
	// 只对DataSort处理
	for k, v := range res.DataSort {
		if _, ok := MultiGoodsMap[v.GoodsID]; ok {
			res.DataSort[k].Multi = 1
			res.DataSort[k].MultiGroupID = MultiGoodsDataMap[v.GoodsID].MultiGroupID
			res.DataSort[k].MultiGroupName = MultiGoodsDataMap[v.GoodsID].MultiGroupName
			res.DataSort[k].MultiGroupDetail = MultiGoodsDataMap[v.GoodsID].MultiGroupDetail
			res.DataSort[k].MultiSort = MultiGoodsDataMap[v.GoodsID].MultiSort
			res.DataSort[k].MultiGroupImage = MultiGoodsIDImageMap[MultiGoodsDataMap[v.GoodsID].MultiGroupID]
			// res.DataSort[k].MultiGroupImage = MultiGoodsIDImageMap[v.GoodsID]
		} else {
			res.DataSort[k].Multi = 0
			// res.DataSort[k].MultiGroupImage
		}
	}
	// return
}
